package timbap.visualizer.impl.context;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import oscP5.OscP5;
import timbap.visualizer.api.context.PluginContext;
import timbap.visualizer.api.context.messaging.MessagingManager;
import timbap.visualizer.api.context.messaging.TimeCodePublisher;
import timbap.visualizer.api.context.messaging.InterpolatingTimeCodePublisher;
import timbap.visualizer.api.context.recorditems.RecordItemManager;
import timbap.visualizer.api.context.textures.TextureCacheManager;
import timbap.visualizer.api.plugin.configuration.PluginManager;
import timbap.visualizer.impl.context.messaging.OscMessagingManagerImpl;
import timbap.visualizer.impl.context.recorditems.DefaultRecordItemManagerImpl;
import timbap.visualizer.impl.context.textures.CircleTextureCacheManagerImpl;
import timbap.visualizer.impl.plugin.configuration.DefaultPluginManagerImpl;

public class ContextInitializationThread extends Thread {

    private static final Log LOG = LogFactory.getLog(ContextInitializationThread.class);

    PluginManager pluginManager;
    PluginContext<OscP5> pluginContext;
    TimeCodePublisher timeCodePublisher;
    OscP5 oscServer;
    
    String progressMessage = null;
    boolean finished = false;
    boolean inProgress = false;


    public ContextInitializationThread(PluginContext<OscP5> pPluginContext,
                                       TimeCodePublisher pTimeCodePublisher,
                                       OscP5 pOscServer) {
        pluginContext = pPluginContext;
        timeCodePublisher = pTimeCodePublisher;
        oscServer = pOscServer;
    }

    public synchronized String getProgressMessage() {
        return progressMessage;
    }

    public synchronized boolean isFinished() {
        return finished;
    }

    public synchronized boolean isInProgress() {
        return inProgress;
    }

    public PluginContext getContext() {
        return pluginContext;
    }

    public PluginManager getPluginManager() {
        return pluginManager;
    }

    public OscP5 getOscServer() {
        return oscServer;
    }

    public TimeCodePublisher getTimeCodePublisher() {
        return timeCodePublisher;
    }

    private TextureCacheManager initTextureCacheManager() {
        TextureCacheManager tTextureCacheManager =
                new CircleTextureCacheManagerImpl(pluginContext.getP5Applet(),
                                                 pluginContext.getCfg(), 
                                                 pluginContext.getPlaylistManager());
        tTextureCacheManager.fillInitialTextureCache();
        return tTextureCacheManager;
    }

    private RecordItemManager initItemManager() {
        RecordItemManager tRecordItemManager = new DefaultRecordItemManagerImpl(pluginContext.getCfg().getItemCount());
        tRecordItemManager.initializeRecordItems(pluginContext.getPlaylistManager());
        return tRecordItemManager;
    }

    private PluginManager initPluginManager() {
        PluginManager tPluginManager = new DefaultPluginManagerImpl();
        tPluginManager.readPluginConfiguration(pluginContext);
        return tPluginManager;
    }

    private MessagingManager<OscP5> initMessagingManager() {
        return new OscMessagingManagerImpl(oscServer, "127.0.0.1", pluginContext.getCfg().getSendingPort());
    }

    @Override
    public void start() {
        inProgress = true;
        super.start();
    }

    @Override
    public void run() {

        progressMessage = "[2/6] Initializing Texture Cache Manager ...";
        LOG.info("Initializing Texture Cache Manager ...");
        pluginContext.setTextureCacheManager(initTextureCacheManager());

        progressMessage = "[3/6] Initializing RecordItem Manager ...";
        LOG.info("Initializing RecordItem Manager ...");
        pluginContext.setRecordItemManager(initItemManager());

        progressMessage = "[4/6] Initializing Messaging Manager ...";
        LOG.info("Initializing Messaging Manager ...");
        pluginContext.setMessagingManager(initMessagingManager());

        progressMessage = "[5/6] Initializing Plugin Manager ...";
        LOG.info("Initializing Plugin Manager ...");
        pluginManager = initPluginManager();

        progressMessage = "[6/6] Initializing Time Code Publisher ...";
        LOG.info("Initializing Time Code Publisher ...");

        if (timeCodePublisher instanceof InterpolatingTimeCodePublisher) {
            ((InterpolatingTimeCodePublisher)timeCodePublisher).setTimeCodeInterpolation(
                    pluginContext.getCfg().getItemCount(),
                    pluginContext.getPlaylistManager().getPlaylistSize(),
                    pluginContext.getCfg().getVelocityFactor());
        }
        timeCodePublisher.setTimeCodeListener(
                pluginManager.getRootPlugin().getTimeCodeListener());

        pluginContext.getMessagingManager().setMessagingProvider(oscServer);

        progressMessage = "DONE.";
        inProgress = false;
        finished = true;
    }


}
